package com.berchen.Fork和Join框架;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

/**
 * Fork/Join框架：就是在必要的情况下，将一个大任务，进行拆分（Fork）成若干个小任务（拆到不可再拆时），再将一个个的小任务运算的结果进行join汇总。
 * ForkJoin框架需要ForkJoinPool的支持才能执行。
 *
 *
 * RecursiveTask与RecursiveAction的区别：RecursiveTask里面的方法都有返回值。
 *
 * invoke与submit的区别：invoke方法有返回值。
 */
public class TestForkAndJoin {

    public static void main(String[] args){

        ForkJoinPool pool=new ForkJoinPool();
        ForkJoinTask<Long> task=new ForkJoinSumCalculate(0L,100000000L);

        Long result = pool.invoke(task);    // 执行并且返回总的结果
        System.out.println(result);
    }

}
class ForkJoinSumCalculate extends RecursiveTask<Long>{

    // 序列号
    private static final long serialVersionUID=-259195479995561737L;

    // 从start计算到end
    private long start;
    private long end;

    // 当分到THURSHOLD，就不将大任务继续分了
    private static final long THURSHOLD=10000L; // 临界值

    public ForkJoinSumCalculate(long start, long end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {

        long length=end-start;
        if(length<=THURSHOLD){

            // 不拆了
            long sum=0L;
            for(long i=start;i<=end;i++){

                sum+=i;
            }
            return sum;
        }
        else {

            long mid=(start+end)/2;

            ForkJoinSumCalculate left=new ForkJoinSumCalculate(start,mid);
            left.fork();  // 进行拆分，同时压入线程队列。

            ForkJoinSumCalculate right=new ForkJoinSumCalculate(mid+1,end);
            right.fork();   // 拆分

            return left.join()+right.join();    // 进行合并

        }
    }
}
